import * as ws from 'websocket';
import { EClientState } from './common/EClientState';
import { BaseServer } from './BaseServer';
import { TransPack } from './common/TransPack';
import { LTLogger } from './logger/LTLogger';
import { ELogLevel } from './common/ELogLevel';
import { GuidHelper } from './GuidHelper';
import { EMessageC2S } from '../../common/EMessageC2S';
import { PakoEx } from '../../LTGame/3rd/pako/PakoEx';
import { MsgPack } from '../../LTGame/3rd/msgpack/MsgPack';

export class BaseClient {

    public id: number;
    public connection: ws.connection;
    public createTick: number;
    public state: EClientState;
    public owner: BaseServer;

    public remoteAddress: string;

    /**
     * tag
     */
    public tag: string = "BaseClient";

    protected _logLevel: ELogLevel = ELogLevel.Log;

    public logger: LTLogger;

    constructor(con: ws.connection, owner: BaseServer) {
        this.owner = owner;
        this.connection = con;
        this.remoteAddress = this.connection.remoteAddress;
        this.createTick = Date.now();
        this.state = EClientState.Wait;
        this.id = GuidHelper.instance.GenGuid();
    }

    public Init() {
        this.logger = new LTLogger(this.tag + "|" + this.remoteAddress, this._logLevel);
        this._OnInit();
        this._InitConnection();
    }

    protected _OnInit() {

    }

    private _InitConnection() {

        this.connection.on("message", (data) => {
            if (this.state == EClientState.Closed) return;
            if (data.type == 'utf8') {
                let parseData = JSON.parse(data.utf8Data) as TransPack;
                if (parseData == null || parseData.type == null) {
                    this.connection.close();
                    return;
                }
                this.owner.ClientPushMsg(parseData, this);
            } else if (data.type == "binary") {
                let uncompressedData = PakoEx.UnCompress(data.binaryData);
                let parseData = MsgPack.Decode(uncompressedData) as TransPack;
                if (parseData == null || parseData.type == null) {
                    this.connection.close();
                    return;
                }
                this.owner.ClientPushMsg(parseData, this);
            } else {
                this.logger.Log(this.remoteAddress + "接收到未识别的消息类型:" + data)
                this.connection.close();
            }
        });

        this.connection.on("close", (reasonCode, description) => {
            if (this.state == EClientState.Closed) return;
            this.state = EClientState.Closed;
            this.logger.Log(this.remoteAddress + "链接已断开");
        });

    }

    public DisConnect() {
        this.connection.close();
    }

    public SendMsg(id: number, msgData: any = null) {
        let sendData = {} as TransPack;
        sendData.type = id;
        if (msgData != null) {
            sendData.data = msgData;
        }

        let sendBin = MsgPack.Encode(sendData);
        let compressedData = PakoEx.Compress(sendBin);
        let buf = Buffer.from(compressedData.buffer, 0, compressedData.length);
        this.connection.sendBytes(buf);

        // let sendJson = JSON.stringify(sendData);
        // this.connection.sendUTF(sendJson);

        /*
        const limit_length = 100;
        if (sendJson.length < limit_length) {
            this.logger.Log('消息下发:' + sendJson);
        } else {
            this.logger.Log('消息下发:' + sendJson.substring(0, limit_length) + "[...]");
        }
        */
    }

    public SendError(errorMsg: string) {
        this.SendMsg(EMessageC2S.Error, errorMsg);
    }

}